<?php
class categoryLogic
{
    //Define constance

    //Init properties
    public    $errorList;
    public    $paramList;
    public    $categoryList;
    protected $properties;

   /**
    * set param of class to default
    * use wizard of PHP
    *
    * @author  TuanNguyen
    * @version Created 2015-01-07
    * @param
    * @return
    */
    function __construct()
    {
        $this->properties   = array();
        $this->errorList    = array();
        $this->paramList    = array();
        $this->categoryList = array();
    }//End __construct

    /**
     * get value of properties of class
     * use wizard of PHP method
     *
     * @author  TuanNguyen
     * @version Created 2015-01-07
     * @param   abstract $propety
     * @return  abstract
     */
    function __get($propety)
    {
        return $this->properties[$propety];
    }//End __get

    /**
     * set value of properties of class
     * use wizard of PHP method
     *
     * @author  TuanNguyen
     * @version Created 2015-01-07
     * @param   abstract $propety
     *          set defined parameter of class
     * @param   abstract $value
     *          set value for defined parameter of class
     * @return  abstract
     */
    function __set($property, $value)
    {
        $this->properties[$property] = $value;
    }//End __set


    /**
     * set request param from input value of form
     * into array
     *
     * @author  TuanNguyen
     * @version Created 2015-01-16
     * @param
     * @return  void
     */
    public function setDefaultParam($b_isPaging = false)
    {
        #Region Init param
        //Set default value for necessary param
        $i_amountPerPage  = Yii::app()->params['DATA_LIMIT'];
        $i_page           = 1;
        $s_filter         = '';
        $s_columnName     = 'insert';
        $s_sortMethod     = Yii::app()->params['DEFAULT_SORT'];
        $i_columnPosition = 0;
        $arr_ColumnLabels = Category::model()->attributeLabels();
        $s_columnLabel    = $arr_ColumnLabels['insert'];
        $bool_IE          = false;
        #EndRegion

        #Region Set input Value into param
        if( strpos( $_SERVER["HTTP_USER_AGENT"], "MSIE" ) !== false ) {
            $bool_IE = true;
        }

        if ( $b_isPaging == true && !isset($_REQUEST['sl_amountPerPage']) ) {
            $i_amountPerPage  = Yii::app()->params['DATA_PER_PAGE'];
        } else if ( $b_isPaging == true && isset($_REQUEST['sl_amountPerPage']) ) {
            $i_amountPerPage = $_REQUEST['sl_amountPerPage'];
        }

        if ( isset($_REQUEST['page']) && !empty($_REQUEST['page']) ) {
            $i_page = $_REQUEST['page'];
        }

        if ( isset($_REQUEST['txt_filter']) ) {
            $s_filter = $_REQUEST['txt_filter'];
        }

        if ( isset($_REQUEST['hid_columnName']) && !empty($_REQUEST['hid_columnName']) ) {
            $s_temp = $_REQUEST['hid_columnName'];
            $s_indexArray  = array_search($s_temp, $arr_ColumnLabels);

            if ( $s_indexArray !== false ) {
                $s_columnName  = $s_indexArray;
                $s_columnLabel = $arr_ColumnLabels[$s_indexArray];
            }
        }//End if

        if ( isset($_REQUEST['hid_columnPosition']) && !empty($_REQUEST['hid_columnPosition']) ) {
            $i_columnPosition = $_REQUEST['hid_columnPosition'];
        }

        if ( isset($_REQUEST['hid_sortMethod']) && !empty($_REQUEST['hid_columnPosition']) ) {
            $s_sortMethod = $_REQUEST['hid_sortMethod'];
        }
        #EndRegion

        #Region Set into paramList
        $this->paramList['dataPerPage']    = $i_amountPerPage;
        $this->paramList['page']           = $i_page;
        $this->paramList['filter']         = $s_filter;
        $this->paramList['columnName']     = $s_columnName;
        $this->paramList['columnLabel']    = $s_columnLabel;
        $this->paramList['sortMethod']     = $s_sortMethod;
        $this->paramList['columnPosition'] = $i_columnPosition;
        $this->paramList['isIEBrowser']    = $bool_IE;
        #EndRegion
    }//End setDefaultParam


    /**
     * Get All category record from database
     * with limit 10000 record
     * sort by descending inserted date
     *
     * @author  TuanNguyen
     * @version Created 2015-01-16
     * @param
     * @return  void
     */
    public function getCategoryListWithLimit()
    {
        $i_amountPerPage  = $this->paramList['dataPerPage'];
        $i_page           = $this->paramList['page'];
        $s_filter         = $this->paramList['filter'];
        $s_columnName     = $this->paramList['columnName'];
        $s_sortMethod     = $this->paramList['sortMethod'];
        $i_columnPosition = $this->paramList['columnPosition'];

        //prepare where statement
        $s_where = "
            `name`        LIKE '%$s_filter%' OR
            `url_mapping` LIKE '%$s_filter%'
        ";

        //prepare order statement
        $s_order = '`'.$s_columnName.'` '.$s_sortMethod;

        //Get total record of filter
        $this->paramList['dataTotal'] = Yii::app()->db->createCommand("Select Count(*) from `category` where $s_where;")->queryScalar();;

        //Get array data of filter
        $this->categoryList = Category::getDataList($i_page, $i_amountPerPage, $s_order, $s_where); 
    }//End getCategoryListWithLimit


    /**
     * create list of all category with level order
     * set into array
     *
     * @author  TuanNguyen
     * @version Created 2015-01-31
     * @param
     * @return  array
     */
    public function initLevelCategoryList()
    {
        //init
        $arr_levelCategoryList   = array();
        $s_prefix                = null;
        $i_parent                = 0;

        //Build categoryList with level order
        self::buildCategoryWithLevelOrder($i_parent, $arr_levelCategoryList, $s_prefix);

        return $arr_levelCategoryList;
    }


    /**
     * get request category and all its child
     * set into array with order by level
     *
     * @author  TuanNguyen
     * @version Created 2015-01-16
     * @param   int $i_key
     *          id of request category, if null get all category
     * @return  void
     */
    public function buildCategoryWithLevelOrder($i_parent, &$arr_levelCategoryList, $s_prefix = "")
    {
        //Init
        $arr_temp         = array();
        $arr_categoryList = $this->categoryList;

        #Region categories-child by id of category-parent
        foreach ( $arr_categoryList as $i_index => $o_category) {
            if($o_category->parent == $i_parent) {
                array_push($arr_temp, $o_category);
            }
        }
        #EndRegion

        foreach ( $arr_temp as $key => $o_category) {
            //set name of category-child with level
            $o_category->name = $s_prefix.$o_category->name;

            //push category object into array
            array_push($arr_levelCategoryList, $o_category);

            //Call this fucntion to get children category
            self::buildCategoryWithLevelOrder($o_category->identification, $arr_levelCategoryList, $s_prefix.'....');
        }
    }//End buildCategoryWithLevelOrder


    /**
     * Get 1 Category object with request param
     *
     * @author  TuanNguyen
     * @version Created 2015-02-05
     * @param
     * @return  boolean
     */
    public function getCategoryByRequest()
    {
        //Init default param
        $i_key                              = $_REQUEST['i_key'];
        $this->paramList['requestCategory'] = null;

        //Check request param from webForm
        if ( !isset($_REQUEST['i_key']) ) {
            $o_error          = new ErrorEntity();
            $o_error->errCode = 'ERR_3';

            //Set into error list
            $this->errorList[] = $o_error;
        }

        if ( count($this->errorList) > 0 ) {
            return false;
        }

        $o_category = Category::getDataByKey($i_key);
        if ( ErrorEntity::isErrorEntity($o_category) ) {
            $this->errorList[] = $o_category;
            return false;
        }

        //Set into param list to parse to view
        $this->paramList['requestCategory'] = $o_category;

        return true;
    }//End getCategoryByRequest


    /**
     * check request param from webForm
     * to update 1 category
     *
     * @author  TuanNguyen
     * @version Created 2015-02-05
     * @param
     * @return  boolean
     */
    public function checkEditRequest()
    {
        //init
        $o_category                         = new Category();
        $this->paramList['requestCategory'] = null;

        #Region set request param into entity
        if ( isset($_REQUEST['item_key']) ) {
            $o_category->key = trim($_REQUEST['item_key']);
        }

        if ( isset($_REQUEST['txt_name']) ) {
            $o_category->name = trim($_REQUEST['txt_name']);
        }

        if ( isset($_REQUEST['txt_urlMapping']) ) {
            $o_category->url_mapping = trim($_REQUEST['txt_urlMapping']);
        }

        //Check category parent
        if ( stringLogic::isString($_REQUEST['sl_parent']) ) {
            $o_category->parent = trim($_REQUEST['sl_parent']);
        }

        //Check category image
        if ( isset($_REQUEST['txt_image']) ) {
            $o_category->image = trim($_REQUEST['txt_image']);
        }

        //Check category description
        if ( isset($_REQUEST['ta_description']) ) {
            $o_category->description = CHtml::encode($_REQUEST['ta_description']);
        }
        #EndRegion

        //Check invalid value of an entity
        $o_category = self::checkValidCategoryEntity($o_category);
        if ( !($o_category instanceof Category) ) {
            //Error list is returned
            $this->errorList = $o_category;
            return false;
        }

        //Set into paramList
        $this->paramList['requestCategory'] = $o_category;

        return true;
    }//End checkEditRequest


    /**
     * if key of category = 0  => insert into database
     * if key of category != 0 => update into database
     *
     * @author  TuanNguyen
     * @version Created 2015-02-12
     * @param
     * @return  void or ErrorEntity
     */
    public function executeRequestCategory()
    {
        $o_category = $this->paramList['requestCategory'];
        if ( !($o_category instanceof Category) ) {
            return false;
        }

        if ( $o_category->key === null || $o_category->key < 1 ) {
            //insert into database
            $o_category = Category::addDataToDb($o_category);
        } else {
            $o_category = Category::updateDataToDb($o_category);
        }

        if ( ErrorEntity::isErrorEntity($o_category) ) {
            $this->errorList[] = $o_category;
            return false;
        }

        //Set into paramList
        $this->paramList['requestCategory'] = $o_category;

        return true;
    }


    /**
     * check request param from webForm
     * for deleting
     *
     * @author  TuanNguyen
     * @version Created 2015-02-25
     * @param
     * @return  boolean
     */
    public function checkDeleteRequest()
    {
        //Init
        $o_primaryError = new ErrorEntity();
        $arr_deletedIds = array();

        if ( !isset($_REQUEST['arr_deleteId'])    || 
             !is_array($_REQUEST['arr_deleteId']) ||
             count($_REQUEST['arr_deleteId']) < 0
           ) {
            $o_error          = clone $o_primaryError;
            $o_error->errCode = 'ERR_7';

            $this->errorList[] = $o_error; 
        } else {
            $arr_deletedIds = $_REQUEST['arr_deleteId'];
        }

        //set into paramList
        $this->paramList['categoryKeyList'] = $arr_deletedIds;

        //There are errors
        if ( count($this->errorList) > 0 ) {
            return false;
        }

        return true;
    }


    /**
     * delete request Ids in database
     *
     * @author  TuanNguyen
     * @version Created 2015-02-25
     * @param
     * @return  boolean
     */
    public function deleteRequestIds()
    {
        //Init
        $s_where      = '';
        $arr_deleteId = $this->paramList['categoryKeyList'];

        foreach ($arr_deleteId as $value) {
            $s_where .= '`identification` = '.$value['value'].' OR ';
        }

        //Cut 3 last character
        $s_where = substr($s_where, 0, -3);

        $o_result = Category::deleteDataToDb($s_where);
        if ( ErrorEntity::isErrorEntity($o_result) ) {
            $this->errorList[] = $o_result;
            return false;
        }

        return true;
    }


    /**
     * set request param from input value of form
     * into array
     *
     * @author  TuanNguyen
     * @version Created 2015-01-11
     * @param
     * @return  void
     */
    public function setUploadingParam()
    {
        //Init
        $this->paramList['arr_fileInput']        = $_FILES['fle_uploadFile'];
        $this->paramList['arr_columnDefinition'] = Category::getDefinitionExcelColumnList();
        $this->paramList['i_fileFormat']         = $_REQUEST['rad_formatFile'];
        $this->paramList['s_sheetName']          = Category::DEFAULT_SHEET_NAME;
        $this->paramList['i_HeaderIndex']        = 1;
        $this->paramList['successCount']         = 0;
        $this->paramList['failingCount']         = 0;
        $arr_errorEntity                         = array();

        //Uploading file use format of user
        if ( $this->paramList['i_fileFormat'] == filesLogic::DATA_FORMAT_CUSTOM ) {
            $this->paramList['s_sheetName']   = $_REQUEST['txt_sheetName'];
            $this->paramList['i_HeaderIndex'] = $_REQUEST['txt_HeaderRowIndex'];
        }//End if

        #Region check request param
        //Check file input existing
        if ( !isset( $this->paramList['arr_fileInput']) || $this->paramList['arr_fileInput'] === null ) {
            $o_error            = new ErrorEntity();
            $o_error->errCode   = 'ERR_3';
            $o_errorTemp->param = array('PARAM_1'=>'Tập tin');

            $arr_errorEntity[] = $o_error;
        }

        if ( $this->paramList['i_fileFormat'] != filesLogic::DATA_FORMAT_CUSTOM && $this->paramList['i_fileFormat'] !== filesLogic::DATA_FORMAT_DEFAULT ) {
            $this->paramList['i_fileFormat'] = filesLogic::DATA_FORMAT_DEFAULT;
        }

        //Check request param of custom FileFormat
        if ( $this->paramList['i_fileFormat'] == filesLogic::DATA_FORMAT_CUSTOM ) {
            $this->paramList['s_sheetName']   = $_REQUEST['txt_sheetName'];
            $this->paramList['i_HeaderIndex'] = $_REQUEST['txt_HeaderRowIndex'];

            if ( !stringLogic::isString($this->paramList['s_sheetName']) ) {
                $o_error          = new ErrorEntity();
                $o_error->errCode = 'ERR_5';
                $o_error->param   = array('PARAM_1'=>'Tên bảng tính', 'PARAM_LINE'=>null);

                $arr_errorEntity[] = $o_error;
            }

            if ( !stringLogic::isString($this->paramList['i_HeaderIndex']) ) {
                $o_error          = new ErrorEntity();
                $o_error->errCode = 'ERR_5';
                $o_error->param   = array('PARAM_1'=>'Dòng tiêu đề', 'PARAM_LINE'=>null);

                $arr_errorEntity[] = $o_error;
            }
        }
        #EndRegion

        if ( count($arr_errorEntity) ) {
            $this->errorList = $arr_errorEntity;
            return false;
        }

        return true;
    }//End setUploadingParam


    /**
     * set request param from input value of form
     * into array
     *
     * @author  TuanNguyen
     * @version Created 2015-01-11
     * @param
     * @return  boolean
     */
    public function getDataFromUploadedFile()
    {
        //Init
        $o_category = new Category();

        //return false if, there are error before
        if ( count($this->errorList) > 0 ) {
            return false;
        }

        //Move upload file to temp folder
        $s_fileURL = filesLogic::uploadFile($this->paramList['arr_fileInput'], filesLogic::DATA_EXTENSIONS);
        if ( is_numeric($s_fileURL) && $s_fileURL > 0 ) {
            $o_error          = new ErrorEntity();
            $o_error->errCode = 'ERR_3';
            $o_error->param   = array('PARAM_1'=>'Tập tin');

            $this->errorList[] = $o_error;
            return false;
        }

        $arr_categoryList = filesLogic::getDataFromExcel(
            $s_fileURL,
            $this->paramList['s_sheetName'],
            $this->paramList['i_HeaderIndex'],
            $this->paramList['arr_columnDefinition'],
            $o_category
        );

        //if array of data is empty return error code
        if ( !is_array($arr_categoryList) || count($arr_categoryList) < 1 ) {
            $o_error          = new ErrorEntity();
            $o_error->errCode = 'ERR_1';
            $o_error->param   = null;

            $this->errorList[] = $o_error;
            return false;
        }

        //Set import result into logic object
        $this->categoryList = $arr_categoryList;

        return true;
    }//End getDataFromUploadedFile


    /**
     * insert/update uploaded data from category list
     * into category table
     *
     * @author  TuanNguyen
     * @version Created 2015-01-12
     * @param
     * @return  boolean
     */
    public function execUploadedDataToDatabase()
    {
        //Init
        $i_successCount = 0;
        $i_failingCount = 0;

        //return false if, there are error before
        if ( count($this->errorList) > 0 ) {
            return false;
        }

        //Loop category in excel file to save into database
        foreach ( $this->categoryList as $index => $o_category ) {
            $s_errLine  = 'Tại dòng '. $index;
            $o_category = self::checkValidCategoryEntity($o_category, $s_errLine);

            //Error list is returned
            if ( !($o_category instanceof Category) ) {
                $this->errorList = array_merge($this->errorList, $o_category);

                //Count amount of failing saving
                $i_failingCount ++;
                continue;
            }

            #Region execute import process
            if ( $o_category->key === null) {
                //insert to database
                $b_result = Category::addDataToDb($o_category);
            } else {
                //update to database, with existed category Id
                $b_result = Category::updateDataToDb($o_category);
            }

            if ( ErrorEntity::isErrorEntity($b_result) ) {
                if ( $b_result->errCode == 'ERR_7') {
                    $b_result->param = array('PARAM_1' => $index);
                } 

                $this->errorList[] = $b_result;

                //Count amount of failing saving
                $i_failingCount ++;
                continue;
            }//End if
            #EndRegion

            //remove success data out of array
            unset($this->categoryList[$index]);

            //Count amount of success saving
            $i_successCount ++;
        }//End foreach

        //Set into paramList to parse to view
        $this->paramList['successCount'] = $i_successCount;
        $this->paramList['failingCount'] = $i_failingCount;

        if ( count($this->errorList) > 0 ) {
            return false;
        }

        return true;
    }//End exectUploadedDataToDatabase


    /**
     * Check valid properties of category entity
     * if not, return error code
     * if null set default value
     *
     * @author  TuanNguyen
     * @version Created 2015-01-13
     * @param   Category $o_category
     *                   Category entity
     * @param   int      $i_index
     *                   Index of entiy if check in array
     * @return  Category or ErrorEntity
     */
    private function checkValidCategoryEntity( Category $o_category, $s_errLine = null )
    {
        //Init
        $arr_errorList = array();
        $o_error       = new ErrorEntity();

        //Check category key
        if ( $o_category->key !== null && !is_numeric($o_category->key) ) {
            $o_errorTemp          = clone $o_error;
            $o_errorTemp->errCode = 'ERR_4';
            $o_errorTemp->param   = array( 'PARAM_1'=>'Mã danh mục', 'PARAM_2'=>'chữ số','PARAM_LINE'=>$s_errLine);

            //Set error entity into error list
            $arr_errorList[] = $o_errorTemp;
        }

        //Check category name
        if ( !stringLogic::isString($o_category->name) ) {
            $o_errorTemp          = clone $o_error;
            $o_errorTemp->errCode = 'ERR_5';
            $o_errorTemp->param   = array('PARAM_1'=>'Tên danh mục', 'PARAM_LINE' => $s_errLine);

            //Set error entity into error list
            $arr_errorList[] = $o_errorTemp;
        }

        #Check urlMapping, set value is category name if empty
        if ( !stringLogic::isString($o_category->url_mapping) && stringLogic::isString($o_category->name) ) {
            //if urlMapping is empty => Convert category name into SEO URL
            $o_category->url_mapping = strtolower(str_replace(' ', '-', $o_category->name));//replace space into _ of category name
            $o_category->url_mapping = stringLogic::convertVNToAlphabet($o_category->url_mapping);//Convert vietnamese to alphabet of category name
        } elseif ( !stringLogic::isString($o_category->url_mapping) && !stringLogic::isString($o_category->name) ) {
            //if urlMapping is empty and category name is empty
            $o_errorTemp          = clone $o_error;
            $o_errorTemp->errCode = 'ERR_5';
            $o_errorTemp->param   = array('PARAM_1'=>'Tiêu đề cho SEO', 'PARAM_LINE' => $s_errLine);

            //Set error entity into error list
            $arr_errorList[] = $o_errorTemp;
        }
        #EndRegion

        #Region Check category parent existing
        if ( $o_category->parent !== null && is_numeric($o_category->parent) === false ) {
            $o_errorTemp          = clone $o_error;
            $o_errorTemp->errCode = 'ERR_4';
            $o_errorTemp->param   = array('PARAM_1'=>'Danh mục cha', 'PARAM_2'=>'chữ số', 'PARAM_LINE'=>$s_errLine);

            //Set error entity into error list
            $arr_errorList[] = $o_errorTemp;
        } elseif ( $o_category->parent !== null && $o_category->parent > 0 && !Category::isExistingCategories($o_category->parent) ) {
            $o_errorTemp          = clone $o_error;
            $o_errorTemp->errCode = 'ERR_6';
            $o_errorTemp->param   = array('PARAM_1'=>$o_category->parent, 'PARAM_LINE' => $s_errLine);

            //Set error entity into error list
            $arr_errorList[] = $o_errorTemp;
        } elseif ( $o_category->parent == null ) {
            $o_category->parent = 0;
        }

        if ( $o_category->parent_name !== null ) {
            //if parent is number, select data by key
            if ( is_numeric( $o_category->parent_name) && $o_category->parent_name > 0 ) {
                $o_categoryParent = Category::model()->getDataByID($o_category->parent_name);
            } else {
                $s_urlMapping     = stringLogic::convertVNToAlphabet( $o_category->parent_name); //Convert vietnamese to alphabet of category name
                $s_urlMapping     = str_replace(' ', '-', $s_urlMapping);//replace space into _ of category name
                $o_categoryParent = Category::model()->findByAttributes(array('url_mapping'=>$s_urlMapping));
            }

            if ( $o_categoryParent === null) {
                $o_errorTemp          = clone $o_error;
                $o_errorTemp->errCode = 'ERR_6';
                $o_errorTemp->param   = array('PARAM_1'=>$o_category->parent, 'PARAM_LINE' => $s_errLine);

                //Set error entity into error list
                $arr_errorList[] = $o_errorTemp;
            } else {
                //Set parentId for category
                $o_category->parent = $o_categoryParent->identification;
            }
        }
        #EndRegion

        //Check category existing in database
        if ( $o_category->key === null ) {
            $s_urlMapping     = stringLogic::convertVNToAlphabet( $o_category->name); //Convert vietnamese to alphabet of category name
            $s_urlMapping     = str_replace(' ', '-', $s_urlMapping);//replace space into _ of category name
            $o_categoryTemp   = Category::model()->findByAttributes(array('url_mapping'=>$s_urlMapping, 'parent' => $o_category->parent));

            if ( $o_categoryTemp instanceof Category ) {
                $o_category->key = $o_categoryTemp->identification;
            }
        }

        //Error exist, return error array
        if ( count($arr_errorList) > 0 ) {
            return $arr_errorList;
        }

        return $o_category;
    }//End checkValidCategoryEntity
}
